package cn.xopencode.userservice.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.xopencode.common.framework.vo.PageResult;
import cn.xopencode.mybatis.core.query.QueryWrapperX;
import cn.xopencode.userservice.convert.DeptConver;
import cn.xopencode.userservice.dal.mysql.dataobject.DeptDO;
import cn.xopencode.userservice.dal.mysql.dataobject.DeptRelationDO;
import cn.xopencode.userservice.dal.mysql.dataobject.UserDO;
import cn.xopencode.userservice.dal.mysql.mapper.DeptMapper;
import cn.xopencode.userservice.dal.mysql.mapper.DeptRelationMapper;
import cn.xopencode.userservice.dal.mysql.mapper.UserMapper;
import cn.xopencode.userservice.rpc.dept.dto.*;
import cn.xopencode.userservice.util.FunUtil;
import com.baomidou.mybatisplus.core.enums.SqlLike;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author xiaodawei
 * @since 2021/9/17
 */
@Service
public class DeptService {


    @Autowired
    private DeptMapper deptMapper;
    @Autowired
    private DeptRelationMapper deptRelationMapper;
    @Autowired
    private UserMapper userMapper;

    public DeptTypeDTO getDeptTypeName(String deptId) {
        DeptTypeDTO deptTypeDTO = new DeptTypeDTO();
        setDeptTypeName(deptId, deptTypeDTO);
        return deptTypeDTO;
    }

    private void setDeptTypeName(String deptId, DeptTypeDTO deptTypeDTO) {
        DeptDO deptDO = deptMapper.selectById(deptId);
        if (1 == deptDO.getType()) {
            deptTypeDTO.setDeptTypeName1(StrUtil.isNotBlank(deptTypeDTO.getDeptTypeName1()) ? deptTypeDTO.getDeptTypeName1() + "," + deptDO.getName() : deptDO.getName());
        } else if (2 == deptDO.getType()) {
            deptTypeDTO.setDeptTypeName2(StrUtil.isNotBlank(deptTypeDTO.getDeptTypeName2()) ? deptTypeDTO.getDeptTypeName2() + "," + deptDO.getName() : deptDO.getName());
        } else if (3 == deptDO.getType()) {
            deptTypeDTO.setDeptTypeName3(StrUtil.isNotBlank(deptTypeDTO.getDeptTypeName3()) ? deptTypeDTO.getDeptTypeName3() + "," + deptDO.getName() : deptDO.getName());
        }
        List<DeptRelationDO> relationDOList = deptRelationMapper.selectList(new QueryWrapperX<DeptRelationDO>().eq("dept_id", deptId));
        if (CollUtil.isNotEmpty(relationDOList)) {
            relationDOList.forEach(deptRelationDO -> {
                DeptDO parentDeptDO = deptMapper.selectById(deptRelationDO.getParentId());
                setDeptTypeName(parentDeptDO.getId(), deptTypeDTO);
            });
        }
    }

    public DeptDTO getDept(String deptId) {
        DeptDTO deptDTO = null;
        DeptDO deptDO = deptMapper.selectById(deptId);
        if (null != deptDO) {
            deptDTO = DeptConver.INSTANCE.convert(deptDO);
        }
        Integer count = userMapper.selectCount(new QueryWrapperX<UserDO>().eq("dept_id", deptId));
        deptDTO.setMembers(count);
        findParentDeptList(deptDTO);
        return deptDTO;
    }

    private void findParentDeptList(DeptDTO deptDTO) {
        List<DeptRelationDO> deptRelationDOList = deptRelationMapper.selectList(new QueryWrapperX<DeptRelationDO>().eq("dept_id", deptDTO.getId()));
        if (CollUtil.isNotEmpty(deptRelationDOList)) {
            List<String> parentDeptIdList = deptRelationDOList.stream().map(DeptRelationDO::getParentId).collect(Collectors.toList());
            List<DeptDO> parentDeptDOList = deptMapper.selectBatchIds(parentDeptIdList);
            List<DeptDTO> parentDeptDTOList = DeptConver.INSTANCE.convert(parentDeptDOList);
            deptDTO.setParentDeptList(parentDeptDTOList);
            for (DeptDTO parentDeptDTO : parentDeptDTOList) {
                findParentDeptList(parentDeptDTO);
            }
        }
    }

    public String CreateDept(CreateDeptDTO createDeptDTO) {
        DeptDO deptDO = DeptConver.INSTANCE.convert(createDeptDTO);
        deptDO.setId(IdUtil.objectId());
        FunUtil.defaultValue(deptDO, createDeptDTO.getUserId(), true);
        if (CollUtil.isNotEmpty(createDeptDTO.getParentIdList())) {
            createDeptRelation(createDeptDTO.getParentIdList(), deptDO.getId(), createDeptDTO.getUserId());
        }
        deptDO.setStatus(1);
        deptDO.setIsDeleted(1);
        deptMapper.insert(deptDO);
        return deptDO.getId();
    }

    public PageResult<DeptDTO> findDeptList(DeptPageDTO deptPageDTO) {
        if (StrUtil.isNotBlank(deptPageDTO.getName())) {
            deptPageDTO.setName(SqlUtils.concatLike(deptPageDTO.getName(), SqlLike.DEFAULT));
        }
        Page<DeptDO> deptDOPage = deptMapper.selectPage(new Page<DeptDO>(deptPageDTO.getPageNo(), deptPageDTO.getPageSize()), new QueryWrapperX<DeptDO>().likeIfPresent("name", deptPageDTO.getName()));
        PageResult<DeptDTO> pageResult = new PageResult().setList(deptDOPage.getRecords()).setTotal(deptDOPage.getTotal());
        return pageResult;

    }

    public Integer updateDept(List<UpdateDeptDTO> updateDeptDTOList) {
        Integer count = 0;
        for (UpdateDeptDTO updateDeptDTO : updateDeptDTOList) {
            DeptDO deptDO = DeptConver.INSTANCE.convert(updateDeptDTO);
            FunUtil.defaultValue(deptDO, updateDeptDTO.getUserId(), false);
            if (CollUtil.isNotEmpty(updateDeptDTO.getParentIdList())) {
                createDeptRelation(updateDeptDTO.getParentIdList(), updateDeptDTO.getId(), updateDeptDTO.getUserId());
            } else {
                deptRelationMapper.delete(new QueryWrapperX<DeptRelationDO>().eq("parent_id", updateDeptDTO.getId()));
            }
            count += deptMapper.updateById(deptDO);
        }
        return count;
    }

    private void createDeptRelation(List<String> parentIdList, String deptId, String userId) {
        parentIdList.forEach(parentId -> {
            deptRelationMapper.insert(new DeptRelationDO() {{
                setId(IdUtil.objectId());
                setDeptId(deptId);
                setParentId(parentId);
                FunUtil.defaultValue(this, userId, true);
            }});
        });
    }

    public Integer updateProperty(List<UpdatePropertyDTO> updatePropertyDTOList) {
        Integer count = 0;
        for (UpdatePropertyDTO updatePropertyDTO : updatePropertyDTOList) {
            if (FunUtil.mustOne(updatePropertyDTO.getStatus(), updatePropertyDTO.getIsDeleted()))
                count += deptMapper.updateById(new DeptDO() {{
                    setId(updatePropertyDTO.getId());
                    FunUtil.defaultValue(this, updatePropertyDTO.getUserId(), false);
                    if (StrUtil.isNotBlank(updatePropertyDTO.getStatus()))
                        setStatus(Integer.valueOf(updatePropertyDTO.getStatus()));
                    if (StrUtil.isNotBlank(updatePropertyDTO.getIsDeleted()))
                        setIsDeleted(Integer.valueOf(updatePropertyDTO.getIsDeleted()));
                }});
        }
        return count;
    }

    public List<DeptDTO> getDeptList(String parentId) {
        List<DeptRelationDO> deptRelationDOList = deptRelationMapper.selectList(new QueryWrapperX<DeptRelationDO>().eq("parent_id", parentId));
        List<String> idList = deptRelationDOList.stream().map(DeptRelationDO::getDeptId).collect(Collectors.toList());
        List<DeptDO> deptDOList = deptMapper.selectBatchIds(idList);
        List<DeptDTO> deptDTOList = DeptConver.INSTANCE.convert(deptDOList);
        return deptDTOList;
    }

    public String getDeptNameList(String deptIds) {
        List<String> list = new ArrayList<>(Arrays.asList(deptIds.split(",")));
        List<DeptDO> deptDOList = deptMapper.selectBatchIds(list);
        List<String> nameList = deptDOList.stream().map(DeptDO::getName).collect(Collectors.toList());
        return String.join(",", nameList);
    }
}
